home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Sound
/
Utilities
/
ST201MusicDrivers Folder
/
Music Drivers
/
STrI.h
< prev
Wrap
Text File
|
1993-11-05
|
26KB
|
632 lines
/* Header file for the SoundTrack interpreting routines: */
/* Copyright © 1991-93 by Frank Seide, Koolbarg 39d, D-22117 Hamburg */
#ifndef __SOUNDTRACKER__
#define __SOUNDTRACKER__
/***** Constants: *****/
#define RESTYPE_SOUNDTRACK 'STrR'
#define CHUNK_SIFF 'SIFF' /* FORM SIFF */
/***** Specification of the SoundTracker ('.MOD') format: *****/
#define MAXPTRS 128 /* Size of pointer table */
#define MAXPTRNS MAXPTRS /* max. number of patterns */
#define AMIGAVOICES 4
#define STDPATLENGTH 64
/* #define AMIGA_PTRNSIZE (STDPATLENGTH * AMIGAVOICES * sizeof (struct AmigaCommand)) */
/* FileInstrData: Instrument descriptor (at the beginning of the file) */
#define MOD_INSTNAME_LEN 22
struct FileInstrData {
char filename[MOD_INSTNAME_LEN]; /* Original Amiga filename of this imstrument */
unsigned int numWords; /* Sample length in words (!) (as used for file parsing) */
int unused : 4; /* (unused, set to zero) */
int fineTune : 4; /* Finetune value (-8…+7 in 16th of a semi tone) */
unsigned int volume : 8; /* Initial volume (0…64) */
unsigned int loopWord; /* Loopstart (in words!) (< 32768), 0 => not looping */
unsigned int loopWords; /* Looplength (in words!) (loopWord+loopWords < 65536) */
/* loopWord = 0 => loopWords is the real sample */
/* length as used by the playing routine. Use */
/* numWords for parsing the file only! */
};
/* AmigaCommand: one '.MOD' file command. Patterns are composed of such commands. */
typedef struct AmigaCommand {
unsigned int InstrHiNibble : 4; /* Number of instrument (hi nibble) */
unsigned int AmigaPeriod : 12; /* Output frequency = 3.579545 MHz / AmigaPeriod */
unsigned int InstrLoNibble : 4; /* Number of inst. (lo nibble), 0 => no change */
unsigned int EffectCmd : 4; /* Effects: Command */
unsigned int EffectArg : 8; /* and operand */
} AmigaCommand, *AmigaCommandPtr;
/* How the commands are interpreted: */
/* (…to be translated) */
/*
* (1) Vorab:
* (a) Die folgende Routine wird i. a. alle 20 ms (50 Hz) durchgeführt,
* beim Amiga ursprünglich im VBL-Interrupt (Name wird hier verwendet).
* Kann durch STCMD_ADJUST_SPEED feinjustiert werden (9.8ms bis 78 ms).
* (b) Sie wird für jede Stimme unabhängig durchgeführt, daher wird im folgenden
* nur eine Stimme betrachtet.
* (2) Alle 20 ms:
* (a) Die Aufruf-Frequenz wird zunächst geteilt durch ws_divisor.
* Der Wert von ws_divisor wird durch STCMD_SET_SPEED gesetzt, Default ist 6.
* (b) Alle ws_divisor wird ein NEUES Kommando geholt, gespeichert für (c)
* und gemäß (3) interpretiert.
* Hier wird das InstrLo/HiNibble und AmigaPeriod ausgewertet,
* sowie der unmittelbare Effekt (EffectCmd) (nur manche Effekte werden
* unmittelbar ausgeführt).
* (c) In allen anderen Aufrufen wird das in (b) gespeicherte EffectCmd
* interpretiert (4) (periodischer Effekt).
* Der Effekt könnte auch von (b) unmittelbar interpretiert worden sein.
* Mit Ausnahme von STCMD_EXTRA wurde dabei jedoch eine andere Routine
* verwendet, z. B. eine zur Übernahme von Parametern für den periodischen
* Effekt.
* (3) Ausführung eines NEUEN Kommandos:
* Wird nur alle ws_divisor 20 ms-Schritte aufgerufen.
* (a) Wenn Instrument > 0, dann Instrumentwechsel.
* Es wird nur der Inhalt des zugehörigen InstrumentRecords in den VoiceRecord
* kopiert, eine Übergabe an die Abspielroutine findet hier NICHT statt.
* Dies passiert NUR bei (b).
* Das Kopieren ist überflüssig, nötig sind nur
* (a1) ein Instrumenten-Index, (a2) Volume / Finetune und (a3) ein Offset-Wert,
* der zunächst auf 0 zu setzen ist (für STCMD_SAMPLE_OFFSET).
* (b) Wenn AmigaPeriod > 0, dann übernehmen in masterPeriod und effectivePeriod.
* (Ausnahme: wenn EffectCmd = STCMD_PORTAMENTO_TO oder
* STCMD_PORT_TO_VOL_SLIDE. Dann wird auch der Ton nicht neu angeschlagen).
* Übernehmen bedeutet, daß der Wert zum nächsten Norm-Ton
* gerundet wird (anhand einer Tabelle).
* Mit Hilfe des Fine-Tune-Wertes wird der Norm-Ton dann modifiziert.
* masterPeriod ist im Normalfall identisch mit dem für die Ausgabe
* verwendeten Wert, Ausnahmen sind Effekte wie Vibrato oder Arpeggio.
* masterPeriod wird durch die Portamento-Effekte verändert.
* Es wird NICHT verändert durch Effekte wie Vibrato oder Arpeggio. Die
* verwenden masterPeriod als Ausgangspunkt für ihren Effekt.
* Nach der Übernahme wird der Ton neu angeschlagen, d. h.
* HIER werden die Sample-Pointer aus den VoiceRecords (evtl. durch (a) gesetzt)
* an die Abspielroutine übergeben.
* Eigentlich können die Sample-Pointer hier direkt aus den InstrumentRecords
* entnommen werden, sofern der Sample-Offset (STCMD_SAMPLE_OFFSET)
* separat gespeichert hier mit eingerechnet wird.
* (c) Ausführung unmittelbarer Effekte durch Aufruf entsprechender Routine.
* Bei STCMD_EXTRA ist die identisch mit der für den periodischen Effekt.
* (4) Ausführung des periodischen Effekts:
* Wird in jeden 20 ms-Schritt aufgerufen mit Ausnahme jeden ws_divisor-ten.
* (a) Der Effekt wird durch Aufruf der entsprechenden Routine ausgeführt.
* Bei STCMD_EXTRA ist die identisch mit der für den unmittelbaren Effekt.
*/
/* Available effect commands: */
#define STCMD_ARPEGGIO 0
#define STCMD_PORTAMENTO_UP 1
#define STCMD_PORTAMENTO_DOWN 2
#define STCMD_PORTAMENTO_TO 3 /* Portamento with specified destination */
/* The destination note is specified in AmigaPeriod. When the command */
/* contains this effect, the note is NOT played again from start, as it would */
/* usually be for all other effects when AmigaPeriod is > 0. */
#define STCMD_VIBRATO 4
#define STCMD_PORT_TO_VOL_SLIDE 5 /* Portamento with destination */
#define STCMD_VIBRATO_VOL_SLIDE 6
#define STCMD_TREMOLO 7
#define STCMD_UNUSED 8 /* ("KarPlusStrong" = TP [0.5 0.5] on samples) */
#define STCMD_SAMPLE_OFFSET 9 /* Start current inst. sample at offset > 0 */
/* The starting point of the instrument sample to be used is specified as */
/* multiples of 256, the offset will be set to (256 * effectArg). */
/* Achtung: im ProTracker wird der Startpunkt bei jedem Aufruf ERHÖHT, */
/* was jedoch z. B. bei SPACE DEBRIS dazu führt, daß ein Instrument fast */
/* nicht mehr zu hören ist. Ein absolutes Setzen klingt so, als ob es so sein soll. */
#define STCMD_VOLUME_SLIDE 10
#define STCMD_POSITION_JUMP 11 /* Go to new song position, pattern from start */
#define STCMD_VOLUME_CHANGE 12 /* Set volume (effectArg 0…64) */
#define STCMD_PATTERN_BREAK 13 /* Immediately end pattern, start next */
#define STCMD_EXTRA 14 /* Extra commands */
/* Hi nibble of effectArg is code of extra command (EXTRA_xxx, see below) */
#define STCMD_SET_SPEED 15 /* Set 50 Hz divisor (effectArg = 0…31) */
/* A SoundTracker pattern line is interpreted all (effectArg) VBL interrupts. */
/* Default value is 6, resulting in 8.3 Hz resolution */
#define STCMD_ADJUST_SPEED 15 /* Fine tuning of VBL irq freq. (effectArg = 32…255) */
/* New VBL irq period = 20 ms *125 /EffectArg (Default is 125 => 20 ms, 50 Hz) */
#define EXTRA_FILTER 0 /* Switch Amiga sound filter on/off (obsolete) */
#define EXTRA_FINE_PORT_UP 1
#define EXTRA_FINE_PORT_DOWN 2
#define EXTRA_GLISS_CONTROL 3
#define EXTRA_VIBRATO_CONTROL 4
#define EXTRA_FINE_TUNE 5
#define EXTRA_LOOP 6
#define EXTRA_TREMOLO_CONTROL 7
#define EXTRA_UNUSED 8
#define EXTRA_RETRIGGER_NOTE 9
#define EXTRA_VOLUME_UP 10
#define EXTRA_VOLUME_DOWN 11
#define EXTRA_NOTE_CUT 12
#define EXTRA_NOTE_DELAY 13
#define EXTRA_PATTERN_DELAY 14
#define EXTRA_UNUSED2 15
/* AmigaPattern: structure of one pattern in the '.MOD' file */
typedef struct AmigaPattern {
AmigaCommand commands[STDPATLENGTH][AMIGAVOICES]; /* 1024 bytes */
} AmigaPattern;
/* The file format itself (don't use this structure, for documentation only) */
struct SoundTrackSpec {
char NameSignature[20]; /* Song name (may be different from file name) */
#define OFFSETINSTR 20 /* Instrument descriptors starting here */
struct FileInstrData fid[31]; /* Inst. descriptors (31 or 15) */
Byte numPointers; /* 0x3b6 / 0x1d6: number of pointers USED */
Byte maxPointers; /* 0x3b7 / 0x1d7; this value is of no value */
Byte oPointers[MAXPTRS]; /* 0x3b8 / 0x1d8: pointer list (always 128 bytes) */
long longFmtSignature; /* 0x438 / - : 31 inst. signature ('M.K.' or 'FLT4') */
struct AmigaPattern patterns[]; /* 0x43c / 0x258: the patterns follow here */
/* Sample0[]; /* Sample data begin after last pattern */
};
/***** Macintosh extended '.MOD' format (proprietary): *****/
/* Warning: the format specification has not yet been finished and may change. */
/* CommandRecord: command record used by V2.0 patterns */
typedef struct CommandRecord {
/* long actionLong; /* $00: 0 => Command is NOP */
int instrument; /* $00: > 0 => set new instrument */
Byte noteCmd; /* $02: > 0 => set new note (contains NOTE_xxx) */
Byte effectCmd; /* $03: > 0 => apply effect (contains EFF_xxx) */
Byte noteValue; /* $04: Note value for NOTE_xxx (as MIDI value) */
Byte effectArg; /* $05: Argument value for effectCmd */
unsigned int extraArg; /* $06: Extra argument (currently unused) */
} CommandRecord, *CommandPtr;
#define cmd_actionLong 0
#define cmd_instrument 0
#define cmd_noteCmd 2
#define cmd_effectCmd 3
#define cmd_noteValue 4
#define cmd_effectArg 5
#define cmd_extraArg 6
#define cmd_SIZEOF 8
enum {
NOTE_IDLE, /* Don't change the note (0) */
NOTE_ON, /* Note on (additionally) */
NOTE_OFF, /* Switch additional note off */
NOTE_SET, /* Release previous, attack new note */
NOTE_HARD_SET, /* Switch off previous, attack new note ('.MOD') */
NOTE_PORTAMENTO_TO, /* Special for EFF_PORTAMENTO_TO */
NOTE_LAST
};
#define MIDI_FIRST_ST 48 /* First MIDI note used in '.MOD' files */
#define MIDI_LAST_ST 83 /* Laest MIDI note used in '.MOD' files */
#define MIDI_NUM 128 /* Number of MIDI notes (including 0 as a dummy) */
/* …to be translated: */
/* Besser: zwei Gruppen von Kommandos */
/* (1) STYLE_ => Stil des Anschlags der Noten (Portamento, Arpeggio etc.) */
/* (2) CONTROL_ => Lautstärke, Stereo, Pattern-Break etc. */
enum {
EFF_IDLE, /* Nix tun (0) */
EFF_ARPEGGIO,
EFF_ARPEGGIO_SYM,
EFF_ARPEGGIO_SYM2,
EFF_PORTAMENTO_UP,
EFF_PORTAMENTO_DOWN,
EFF_PORTAMENTO_TO, /* Accompanied by NOTE_PORTAMENTO_TO */
EFF_VIBRATO, /* Lo-Nibble: Amplitude, Hi-Nibble: Frequenz */
EFF_PORT_TO_VOL_SLIDE, /* Portamento mit Zielangabe */
EFF_VIBRATO_VOL_SLIDE,
EFF_TREMOLO,
EFF_SAMPLE_OFFSET, /* Aktuelles Instrument nicht am Beginn starten */
EFF_VOLUME_STEP, /* Einen Schritt in der Lautstärke */
EFF_VOLUME_SLIDE, /* Pro VBL einen Schritt in der Lautstärke */
EFF_NOTE_STEP, /* Einen Schritt in der Note (hoch oder runter) */
EFF_NOTE_SLIDE, /* Pro VBL einen solchen Schritt */
EFF_POSITION_JUMP, /* neue Song-Position, Pattern von vorne */
EFF_VOLUME_CHANGE, /* (Argument 0..64) */
EFF_STEREO_CHANGE, /* (Argument 128..255) */
EFF_PATTERN_BREAK, /* Pattern beenden */
EFF_SET_VBL_DIVISOR, /* (Argument 0..31) */
EFF_SET_VBL_ADJUST, /* (Argument 32..255) */
EFF_FINE_PORT_UP,
EFF_FINE_PORT_DOWN,
EFF_GLISS_TYPE,
EFF_VIBRATO_TYPE, /* Vibrato-Typ VIBRATO_TYPE_SINE oder _RAMP */
EFF_FINE_TUNE,
EFF_FOR,
EFF_NEXT,
EFF_TREMOLO_TYPE,
EFF_RETRIGGER_NOTE,
EFF_NOTE_CUT,
EFF_NOTE_DELAY,
EFF_DELAY, /* Um effectArg Noten verzögern */
EFF_END, /* Ende des Stückes */
EFF_LAST
};
/* EFF_VIBRATO_TYPE: wie wird Periode bei Vibrato moduliert ? */
#define VIBRATO_TYPE_SINE 0 /* Sinus */
#define VIBRATO_TYPE_RAMP_DOWN 1 /* steigende Rampe (-1…+1) (falld. für Freq.) */
#define VIBRATO_TYPE_RAMP_UP 4 /* fallende Rampe (+1…-1) (Rampen ungerade) */
#define VIBRATO_TYPE_RECT 2 /* Rechteck (+1, -1) */
#define VIBRATO_TYPE_RECT2 3 /* (Mehrdeutigkeit im ProTr.: auch Rechteck) */
#define VIBRATO_TYPE_TRI 5 /* symmetrisches Dreieck */
#define VIBRATO_KEEP_PHASE 0x80 /* Bei Anschlag Phase NICHT zurücksetzen! */
/***** Data structures for internal representation of song file: *****/
#define POSITION_LEFT 0
#define POSITION_CENTER 32
#define POSITION_RIGHT 64
#define POSITION_SURROUND 96
#define POSITION_DEFAULT 0xff
#define POSITION_NO_CHANGE 0xfe
#define VOLUME_DEFAULT 0xff
#define VOLUME_NO_CHANGE 0xfe
/* Constants for values that may be stored in the speed field: */
/* Warning: the SoundTracker playing mechanism represents a finite state machine. */
/* The execution of finite state machines can not be reversed in any cases, so */
/* playing a song backwards may result in wrong settings of VBLDivisor, */
/* VBLAdjust and playingTime. Furthermore, jumps in the song can not be reversed. */
#define SPEED_NORMAL 1 /* Normal playing speed */
#define SPEED_HOLD 0 /* Hold the music (different from pause) */
#define SPEED_BACKWARDS -1 /* May not work in any cases! */
#define SPEED_FASTFORWARD 2 /* Fast forward: values > 1 */
#define SPEED_FASTERFORWARD 4
#define SPEED_EVENFASTERFORWARD 8
#define SPEED_REWIND -2 /* Rewind: values < -1 */
#define SPEED_FASTERREWIND -4
#define SPEED_EVENFASTERREWIND -8
/* Workspace: variables used when playing back a song */
typedef struct Workspace {
signed char speed; /* $00: Soviele Ticks aufeinmal (Spulen; 1 = normal) */
Byte ffCounter; /* $01: Zähler dafür */
unsigned int VBLFrames; /* $02: soviele Bytes pro VBL-Tick */
Byte VBLDivisor; /* $04: VBL-Teiler, Default = 6 */
Byte songPos; /* $05: Byte ? */
int pattPos; /* $06: aktuelle Pattern-Position (Zeilenindex) */
Byte cycle; /* $08: "VBL"-Zähler */
Boolean pattBreak; /* $09: Break-Flag für Patterns */
Boolean loopDetect; /* $0a: Loop-Erkennung ? */
Boolean looping; /* $0b: Loop wurde erkannt */
Boolean endOfSong; /* $0c: Ende des Stückes (keine neuen Noten mehr) */
Boolean nextOne; /* $0d: Ende oder Loop; nächstes Stück nehmen */
int speedFactor; /* $0e: Externer Faktor vom User-Interface (in %) */
unsigned int VBLAdjust; /* $10: ProTrkr. 2.0-VBL-Adjust 32/125 … 255/155 ≈ 0.256 … 2.04 */
/* VBLAdjust = BPM für VBLDivisor = 6 !! */
int overwriteVoice; /* $12: Echtzeit-Overwrite dieses Kanals */
CommandRecord overwriteCommand; /* $14: Overwrite dieses Kommandos (0 = inaktiv) */
Fixed playingTime; /* $1c: Spielzeit in Sekunden */
Fixed prevHardFreq; /* $20: auf dieser hardFreq basieren aktuelle Rates */
int ** periodTable; /* $24: Handle auf Amiga-Perioden der MIDI-Töne */
Byte delay; /* $28: Delay-Counter */
Byte patternStart; /* $29: EFF_PATTERN_BREAK mit Pos. > 0 */
Byte reserved2[16] ; /* $2a */
int numVoices; /* $3a: Anzahl Stimmen (Anzahl Voice-Records) */
Handle voices; /* $3c: Handle auf Voice-Records */
Boolean hold; /* $40: Sample nicht updaten (internes Flag) */
Byte prevSongPos; /* $41: vorige Song-Position */
int prevPattPos; /* $42: vorige Pattern-Position */
Fixed requestedPlayingTime; /* $44: Jump to value stored here (WO) */
Byte reserved[0x8c]; /* $48 */
} WorkspaceRecord, *WorkspacePtr;
#define ws_speed 0x00
#define ws_ffCounter 0x01
#define ws_VBLFrames 0x02
#define ws_VBLDivisor 0x04
#define ws_songPos 0x05
#define ws_pattPos 0x06
#define ws_cycle 0x08
#define ws_pattBreak 0x09
#define ws_loopDetect 0x0a
#define ws_looping 0x0b
#define ws_endOfSong 0x0c
#define ws_nextOne 0x0d
#define ws_speedFactor 0x0e
#define ws_VBLAdjust 0x10
#define ws_overwriteVoice 0x12
#define ws_overwriteCommand 0x14
#define ws_playingTime 0x1c
#define ws_prevHardFreq 0x20
#define ws_periodTable 0x24
#define ws_delay 0x28
#define ws_patternStart 0x29
#define ws_numVoices 0x3a
#define ws_voices 0x3c
#define ws_hold 0x40
#define ws_prevSongPos 0x41
#define ws_prevPattPos 0x42
#define ws_requestedPlayingTime 0x44
#define ws_reserved 0x48
#define ws_SIZEOF 0xd4
/* InstrumentRecord: internal representation of an instrument */
typedef struct InstrumentRecord { /* Don't use, will change */
/* …später: Instrument-Sharing (sinnvoll, da Instrumente viel Platz brauchen) */
/* int numRefs; /* $xx: so oft wird dieses Instrument verwendet */
/* int locks; /* $xx: so oft gelockt (nur HUnlock, wenn locks = 0) */
/* …ganze Ranges angeben! Z.B. Array */
/* Byte note; /* $xx: dieser Ton ist gespeichert (MIDI-Angabe) */
/* Fixed sampleFreq; /* $xx: Original-Samplefrequenz */
Handle sample; /* $00: Zeiger auf 1. Sample …wird Offset in dieses Handle */
/* Die folgenden Angaben enthalten 2^ldOverSampling als Faktor: */
unsigned long length; /* $04: Offset hinter letztes Originalsample */
unsigned long loopStart; /* $08: hier beginnt Loop (z.Zt. length-loopLength) */
unsigned long loopLength; /* $0c: Distanz vom Ende zum Loop-Beginn */
/* Zusatzinfo: */
Byte initialVolume; /* $10: Default-Lautstärke 0…64 (Übern. bei Inst.-Wechsel) */
Byte instrumentStPos; /* $11: Stereo-Position (Default des Instruments) */
Byte ldOverSampling; /* $12: Wieoft Frequenz shiften (0..3) ? */
Byte initialFineTune; /* $13: Frequenzjustage */
Byte reserved[28];
/* Name: */
Str63 name; /* $30: Name des Instruments */
} InstrumentRecord, *InstrumentPtr;
#define ins_sample 0x00
#define ins_length 0x04
#define ins_loopStart 0x08
#define ins_loopLength 0x0c
#define ins_initialVolume 0x10
#define ins_instrumentStPos 0x11
#define ins_ldOverSampling 0x12
#define ins_initialFineTune 0x13
#define ins_name 0x30
#define ins_SIZEOF 0x70
/* TimeTrackRecord: extra track for timing information (currently not used) */
typedef struct TimeTrackRecord { /* Specifies duration of pattern line */
unsigned int stepNumer; /* $00: Numerator (0 => next line immediately) */
unsigned int stepDenom; /* $02: Denominator */
} TimeTrackRecord, * TimeTrackPtr, ** TimeTrackHandle;
#define tt_stepNumer 0
#define tt_stepDenom 2
#define tt_SIZEOF 4
/* PatternRecord: a pattern in memory */
#define MAXTRACKS 32
typedef struct PatternRecord {
unsigned int commandsOffset; /* $00: offset to commands */
int res1; /* $02 */
/* References: */
unsigned int songRefs; /* $04: How often used in song ? */
unsigned int spareRefs; /* $06: How often used in spare ? */
unsigned int undoRefs; /* $08: How often used in undo buffer ? */
unsigned int clipBoardRefs; /* $0a: How often used in clipboard ? */
long res2; /* $0c */
/* Pattern dimensions: can be changed with ReshapePattern() */
/* (actually, ReshapePattern() never decreases any dimension) */
unsigned int numTracks; /* $10: number of active tracks */
unsigned int length; /* $12: number of active lines */
unsigned int width; /* $14: width of array (≥ numVoices) */
unsigned int height; /* $16: height of array (≥ length) */
unsigned int rowBytes; /* $18: length of line in bytes (for player) */
Byte res3[6]; /* $1a */
/* More info: */
Str255 name; /* $20: Pattern name */
Byte localKey; /* $120: key (-1: use globalKey) */
Byte res4; /* $121 */
Byte patternDefStPos[MAXTRACKS]; /* $122: Default stereo positions */
int res5; /* $142 */
/* Time-Track: */
TimeTrackHandle timeTrack; /* $144 */
/* Contents of pattern: */
/* Warning: always access via commandOffset (see above), so more fields */
/* can be inserted in PatternRecord! */
CommandRecord commands[]; /* $148: Command array */
} PatternRecord, *PatternPtr, **PatternHandle;
typedef PatternHandle ** PatternListHandle; /* Handle to array of PatternHandles */
#define pat_commandsOffset 0x00
#define pat_songRefs 0x04
#define pat_spareRefs 0x06
#define pat_undoRefs 0x08
#define pat_clipBoardRefs 0x0a
#define pat_numTracks 0x10
#define pat_length 0x12
#define pat_width 0x14
#define pat_height 0x16
#define pat_rowBytes 0x18
#define pat_name 0x20
#define pat_localKey 0x120
#define pat_patternDefStPos 0x122
#define pat_timeTrack 0x144
#define pat_commands 0x148
#define pat_SIZEOF 0x148
/* SoundTrack: main data structure and handle to song in memory */
/* Commented fields may be accessed directly. However, to access the workspace */
/* and instruments, use corresponding routines to obtain a pointer. This allows */
/* changes in the data structure. */
/* This record cannot be shared, a SoundTrack can only be played once at a time! */
typedef struct SoundTrack {
struct PChannel * pchannel; /* $00: Linked PChannel (NULL => none) */
char signature[21]; /* $04: Original '.MOD' song name */
Byte ldOverSampling; /* $19: Apply anti-alias filter at load time (RO) */
Boolean check; /* $1a: Is result of structure check, don't play! */
Byte paddedInstruments; /* $1b */
WorkspaceRecord workspace; /* $1c: Workspace (use routine to get address!) */
Byte numInstruments; /* $f0: Number of instruments */
Byte pad1a; /* $f1 */
Byte pad1b; /* $f2 */
/* Pointer list: */
Byte numPointers; /* $f3: Number of pointers USED (-> song length) */
Handle pointers; /* $f4: Handle to pattern references */
/* Reference Count: */
int refCount; /* $f8: Freigabe nur bei refCount = 1 */
/* Patterns: */
int numPatterns; /* $fa: Number of patterns */
PatternListHandle patterns; /* $fc: Handle to list of pattern handles */
/* Dateityp ('M.K.', 'PRO ' (mit ProTracker-Eff.), 'FLT4/8', 'OLD ' (15 Stimmen), 'OKTA'): */
OSType typeID; /* $100: Dateityp */
long paddedBytes; /* $104 */
Byte filler[12];
/* Extended song info for editor: */
Rect windowRect; /* $114: 'rect' of edit window (pos, size) */
Byte globalKey; /* $11c: 'KEY_' main key of the song (MIDI-like) */
Byte initialVBLDivisor; /* $11d: 'SSPD' Initial VBL divisor */
unsigned int initialVBLAdjust; /* $11e: 'SADJ' Initial VBL period */
Fixed totalPlayingTime; /* $120: 'TTIM' Total playing time in seconds */
unsigned int beatsPerMinute; /* $104: 'BPM_' (ersatzweise aus Songp. 2 geschätzt) */
Byte res[10]; /* $126 */
Str255 title; /* $130: 'NAME' Song title */
Str255 author; /* $230: 'AUTH' Author (name / address) */
Str255 arrangeur; /* $330: 'ARRG' Arranger (name / address) */
Str255 copyright; /* $430: '(c) ' Copyright notice */
Str255 annotation; /* $530: 'ANNO' Author's annotation */
Str255 reservedStr; /* $630: …wech */
/* Instruments (do NOT access directly, this WILL change)! */
InstrumentRecord instruments[]; /* $730: Array of InstrumentRecords */
} SoundTrack, * SoundTrackPtr, ** SoundTrackHandle;
#define st_pchannel 0x00
#define st_signature 0x04
#define st_ldOverSampling 0x19
#define st_check 0x1a
#define st_paddedInstruments 0x1b
#define st_workspace 0x1c
#define st_numInstruments 0xf0
#define st_numPointers 0xf3
#define st_pointers 0xf4
#define st_refCount 0xf8
#define st_numPatterns 0xfa
#define st_patterns 0xfc
#define st_typeID 0x100
#define st_paddedBytes 0x104
#define st_windowRect 0x114
#define st_globalKey 0x11c
#define st_initialVBLDivisor 0x11d
#define st_initialVBLAdjust 0x11e
#define st_totalPlayingTime 0x120
#define st_beatsPerMinute 0x124
#define st_title 0x130
#define st_author 0x230
#define st_arrangeur 0x330
#define st_copyright 0x430
#define st_annotation 0x530
#define st_instruments 0x730
/***** Error codes: *****/
#define errBadFormat badMDBErr /* GetSoundTrack(): wrong or unsupp. file format */
/***** Function prototypes: *****/
/*** Reading and writing song files: ***/
/* Note: writing NOT implemented yet */
extern pascal OSErr GetSoundTrack (int vRefNum, StringPtr fName, Byte ldOverSampling,
SoundTrackHandle *soundTrackHandle, Boolean check);
extern pascal OSErr HGetSoundTrack (int vRefNum, long dirID, StringPtr fName, Byte ldOverSampling,
SoundTrackHandle *soundTrackHandle, Boolean check);
extern pascal OSErr FSpGetSoundTrack (FSSpecPtr spec, Byte ldOverSampling,
SoundTrackHandle *soundTrackHandle, Boolean check);
extern pascal OSErr PutSoundTrack (int vRefNum, StringPtr fName, SoundTrackHandle sth);
extern pascal OSErr HPutSoundTrack (int vRefNum, long dirID, StringPtr fName, SoundTrackHandle sth);
extern pascal OSErr FSpPutSoundTrack (FSSpecPtr spec, SoundTrackHandle sth);
/*** Handling song resources: ***/
/* Note: this enables you reading '.MOD' “files” from resources! */
extern pascal OSErr GetSoundTrackResource (ResType resType, int resID, Byte ldOverSampling,
SoundTrackHandle *soundTrackHandle, Boolean check);
extern pascal OSErr GetNamedSoundTrackResource (ResType resType, StringPtr resName,
Byte ldOverSampling, SoundTrackHandle *soundTrackHandle, Boolean check);
extern pascal OSErr AddSoundTrackResource (int resType, int resId,
Boolean extraSndRes, SoundTrackHandle sth);
/*** Memory management: ***/
extern pascal OSErr NewSoundTrack (int numVoices, int numPatterns, int numInstruments,
SoundTrackHandle *sth);
extern pascal void DisposeSoundTrack (SoundTrackHandle sth);
extern pascal OSErr MoreInstruments (SoundTrackHandle sth, int numInstruments);
extern pascal OSErr MoreVoices (SoundTrackHandle sth, int numVoices);
extern pascal OSErr MorePatterns (SoundTrackHandle sth, int numPatterns);
extern pascal OSErr ReshapePattern (SoundTrackHandle sth, int index, int newTracks, int newLength);
/*** Interfacing the playing routines: ***/
extern pascal struct SoundTrack * LockSoundTrack (SoundTrackHandle soundTrack);
extern pascal void UnlockSoundTrack (SoundTrackHandle soundTrack);
extern pascal void LinkSoundTrack (SoundTrackHandle soundTrack, struct PChannel * pc);
extern pascal void UnlinkSoundTrack (SoundTrackHandle soundTrack);
extern pascal void UpdateSoundTrack (SoundTrackHandle soundTrack);
/*** Data structure access: ***/
extern pascal InstrumentPtr GetSoundTrackInstrument (SoundTrackHandle sth, int i);
extern pascal WorkspacePtr GetSoundTrackWorkspace (SoundTrackHandle sth);
extern pascal PatternHandle GetSoundTrackPattern (SoundTrackHandle sth, int i);
/*** Other routines: ***/
extern pascal OSErr RecalcSoundTrack (SoundTrackHandle sth);
extern pascal void SetSoundTrackStereoPosition (SoundTrackHandle sth, int i, Byte pos);
extern pascal int VersionSoundTrack();
extern pascal void CopyrightSoundTrack (StringPtr s);
#endif